﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LibEBML.Common
{
    public class TrackEntry : MatroskaBase
    {
        protected override void Initialize()
        {
            var v1 = container[0xe0].FirstOrDefault() as EBMLContainer;
            if (v1 != null)
            {
                Video = new VideoInfo(v1);
            }
            var a1 = container[0xe1].FirstOrDefault() as EBMLContainer;
            if (a1 != null)
            {
                Audio = new AudioInfo(a1);
            }
            var tid = container[0x73c5].FirstOrDefault() as EBMLType<ulong>;
            if (tid != null)
            {
                TrackUID = (long)tid.Value;
            }
            var t2 = container[0xd7].FirstOrDefault() as EBMLType<ulong>;
            if (t2 != null)
            {
                TrackNumber = (int)t2.Value;
            }
            var t3 = container[0x83].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                TrackType = (int)t3.Value;
            }
            var dd = container[0x23e383].FirstOrDefault() as EBMLType<ulong>;
            if (dd != null)
            {
                DefaultDuration = (long)dd.Value;
            }
            var nm = container[0x536e].FirstOrDefault() as EBMLString;
            if (nm != null)
            {
                Name = nm.Value;
            }
            nm = container[0x86].FirstOrDefault() as EBMLString;
            if (nm != null)
            {
                CodecID = nm.Value;
            }
            var b = container[0x63a2].FirstOrDefault() as EBMLBinary;
            if (b != null)
            {
                b.BaseSource.Position = b.DataPosition;
                byte[] buff = new byte[b.Size];
                b.BaseSource.Read(buff, 0, buff.Length);
                CodecPrivate = buff;
            }

            var cts = container[0x06d80].FirstOrDefault() as EBMLContainer;
            if (cts != null)
            {
                ContentEncodings = cts[0x6240].Select(m => new ContentEncoding(m as EBMLContainer)).ToList();
            }
            t3 = container[0xb9].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                FlagEnable = (t3.Value != 0);
            }
            t3 = container[0x88].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                FlagDefault = (t3.Value != 0);
            }
            t3 = container[0x55aa].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                FlagForced = (t3.Value != 0);
            }
            t3 = container[0x9c].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                FlagLacing = (t3.Value != 0);
            }
        }
        protected override void InitDefaultValues()
        {
            FlagDefault = true;
            FlagEnable = true;
            FlagLacing = true;
            FlagForced = false;
            DefaultDuration = 1;
            TrackTimecodeScale = 1;
            Language = "eng";
            CodecDecodeAll = true;
        }

        public TrackEntry(EBMLContainer container)
            : base(container)
        {

        }

        public int TrackType { get; set; }
        public int TrackNumber { get; set; }
        public long TrackUID { get; set; }
        public bool FlagEnable { get; set; }
        public bool FlagDefault { get; set; }
        public bool FlagForced { get; set; }
        public bool FlagLacing { get; set; }
        public long MinCache { get; set; }
        public long MaxCache { get; set; }
        public long DefaultDuration { get; set; }
        public decimal TrackTimecodeScale { get; set; }
        public string Name { get; set; }
        public string Language { get; set; }
        public string CodecID { get; set; }
        public byte[] CodecPrivate { get; set; }
        public string CodecName { get; set; }
        public string CodecSettings { get; set; }
        public string CodecInfoURL { get; set; }
        public string CodecDownloadURL { get; set; }
        public bool CodecDecodeAll { get; set; }
        public long TrackOverlay { get; set; }

        public VideoInfo Video { get; set; }
        public AudioInfo Audio { get; set; }

        public IList<ContentEncoding> ContentEncodings { get; set; }
    }
    public class VideoInfo : MatroskaBase
    {


        public VideoInfo(EBMLContainer container)
            : base(container)
        {

        }
        protected override void Initialize()
        {
            var t1 = container[0xb0].FirstOrDefault() as EBMLType<ulong>;
            if (t1 != null)
            {
                PixelWidth = (int)t1.Value;
            }
            t1 = container[0xba].FirstOrDefault() as EBMLType<ulong>;
            if (t1 != null)
            {
                PixelHeight = (int)t1.Value;
            }

            t1 = container[0x54b0].FirstOrDefault() as EBMLType<ulong>;
            if (t1 != null)
            {
                DisplayWidth = (int)t1.Value;
            }
            else
            {
                DisplayWidth = PixelWidth;
            }
            t1 = container[0x54ba].FirstOrDefault() as EBMLType<ulong>;
            if (t1 != null)
            {
                DisplayHeight = (int)t1.Value;
            }
            else
            {
                DisplayHeight = PixelHeight;
            }
            t1 = container[0x54b2].FirstOrDefault() as EBMLType<ulong>;
            if (t1 != null)
            {
                DisplayUnit = (int)t1.Value;
            }


            var b = container[0x2eb524].FirstOrDefault() as EBMLBinary;
            if (b != null)
            {
                b.BaseSource.Position = b.DataPosition;
                byte[] buff = new byte[b.Size];
                b.BaseSource.Read(buff, 0, buff.Length);
                ColourSpace = buff;
            }
        }
        protected override void InitDefaultValues()
        {

        }
        public bool FlagInterlaced { get; set; }
        public int StereoMode { get; set; }
        public int PixelWidth { get; set; }
        public int PixelHeight { get; set; }
        public int DisplayWidth { get; set; }
        public int DisplayHeight { get; set; }
        public int DisplayUnit { get; set; }
        public int AspectRatioType { get; set; }
        public byte[] ColourSpace { get; set; }
        public decimal GammaValue { get; set; }

    }
    public class AudioInfo : MatroskaBase
    {


        public AudioInfo(EBMLContainer container)
            : base(container)
        {

        }
        protected override void Initialize()
        {
            var t1 = container[0xb5].FirstOrDefault() as EBMLType<decimal>;
            if (t1 != null)
            {
                SamplingFrequency = (decimal)t1.Value;
            }
            t1 = container[0x78b5].FirstOrDefault() as EBMLType<decimal>;
            if (t1 != null)
            {
                OutputSamplingFrequency = (decimal)t1.Value;
            }
            var t2 = container[0x9f].FirstOrDefault() as EBMLType<ulong>;
            if (t2 != null)
            {
                Channels = (int)t2.Value;
            }
            t2 = container[0x6264].FirstOrDefault() as EBMLType<ulong>;
            if (t2 != null)
            {
                BitDepth = (int)t2.Value;
            }
            var b = container[0x7d7b].FirstOrDefault() as EBMLBinary;
            if (b != null)
            {
                b.BaseSource.Position = b.DataPosition;
                byte[] buff = new byte[b.Size];
                b.BaseSource.Read(buff, 0, buff.Length);
                ChannelPositions = buff;
            }

        }
        protected override void InitDefaultValues()
        {
            SamplingFrequency = 8000;
            OutputSamplingFrequency = 8000;
            Channels = 1;
        }

        public decimal SamplingFrequency { get; set; }
        public decimal OutputSamplingFrequency { get; set; }
        public int Channels { get; set; }
        public byte[] ChannelPositions { get; set; }
        public int BitDepth { get; set; }

    }
    public class ContentEncoding : MatroskaBase
    {


        public ContentEncoding(EBMLContainer container)
            : base(container)
        {

        }
        protected override void Initialize()
        {
            var v1 = container[0x5034].FirstOrDefault() as EBMLContainer;
            if (v1 != null)
            {
                Compression = new ContentCompression(v1);
            }
        }
        protected override void InitDefaultValues()
        {
            ContentEncodingScope = 1;
            ContentEncodingOrder = 0;
        }
        public int ContentEncodingOrder { get; set; }
        public int ContentEncodingScope { get; set; }
        public int ContentEncodingType { get; set; }
        public ContentCompression Compression { get; set; }
        public ContentEncryption Encryption { get; set; }
    }
    public class ContentCompression : MatroskaBase
    {


        public ContentCompression(EBMLContainer container)
            : base(container)
        {

        }
        protected override void Initialize()
        {
            var t3 = container[0x4254].FirstOrDefault() as EBMLType<ulong>;
            if (t3 != null)
            {
                ContentCompAlgo = (int)t3.Value;
            }
            var b = container[0x4255].FirstOrDefault() as EBMLBinary;
            if (b != null)
            {
                b.BaseSource.Position = b.DataPosition;
                byte[] buff = new byte[b.Size];
                b.BaseSource.Read(buff, 0, buff.Length);
                ContentCompSettings = buff;
            }
        }
        protected override void InitDefaultValues()
        {
            ContentCompAlgo = 0;
        }
        public int ContentCompAlgo { get; set; }
        public byte[] ContentCompSettings { get; set; }
    }
    public class ContentEncryption : MatroskaBase
    {

        public ContentEncryption(EBMLContainer container)
            : base(container)
        {

        }
        protected override void Initialize()
        {

        }
        protected override void InitDefaultValues()
        {
        }
    }
}
